package com.codeoss.framework.view.util;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.codeoss.framework.context.YunContext;
import com.codeoss.framework.data.metadata.Column;
import com.codeoss.framework.data.metadata.Query;
import com.codeoss.framework.data.metadata.TableData;
import com.codeoss.framework.data.store.ITableStore;
import com.codeoss.framework.expression.Expression;
import com.codeoss.framework.expression.IScriptServiceStore;
import com.codeoss.framework.util.LookupInfo;
import com.codeoss.framework.util.StringUtils;
import com.codeoss.framework.view.component.Component;
import com.codeoss.framework.view.component.IDataBindSource;
import com.codeoss.framework.view.component.IDataBinding;
import com.codeoss.framework.view.component.IDataType;
import com.codeoss.framework.view.component.IFormFieldExpression;
import com.codeoss.framework.view.component.ILookup;
import com.codeoss.framework.view.component.IVarName;
import com.codeoss.framework.view.component.Image;
import com.codeoss.framework.view.component.Page;
import com.codeoss.framework.view.component.Table;
import com.codeoss.framework.view.component.mobile.MListView;
import com.codeoss.framework.view.datasource.DataSourceConfig;
import com.codeoss.framework.view.model.SelectItem;
import com.codeoss.framework.view.pagebean.crud.PageBeanCRUDUtil;
import com.codeoss.framework.view.pagebean.crud.SelectRequest;
import com.codeoss.framework.view.pagebean.crud.SelectResponse;
import com.codeoss.framework.view.service.IVariableService;

@Service
public class ComponentDataUtil {
	@Autowired
	private PageBeanCRUDUtil pageBeanCRUDUtil;
	@Autowired
	private ITableStore tableStore;
	@Autowired
	private LookupUtil lookupUtil;
	@Autowired
	private DataSourceUtil dataSourceUtil;
	@Autowired
	private IVariableService variableService;
	@Autowired
	private PageBeanUtil pageBeanUtil;
	@Autowired
	private IScriptServiceStore scriptServiceStore;
	public void getTableComponentData(YunContext yunContext,Page page,Table tableComponent,List<IDataBinding> dataBindingList,Query query) {
		DataSourceConfig dataSourceConfig=page.getDataSourceConfigById(tableComponent.getDataSource());
		dataSourceUtil.fillQuery(yunContext, query, dataSourceConfig);
		TableData tableData=pageBeanCRUDUtil.getTableData(yunContext, page, tableComponent, query);
		Map<String, List<SelectItem>> selectItemMap = new HashMap<String, List<SelectItem>>();
		yunContext.setAttribute(tableComponent.getId() + "_tabledata", tableData);
		yunContext.setAttribute(tableComponent.getId() + "_selectItemMap", selectItemMap);
		if (tableData.getData().size() == 0) {
			return;
		}
		for (int j = 0; j < dataBindingList.size(); j++) {
			IDataBinding dataBinding = dataBindingList.get(j);
			Component component = (Component) dataBinding;
			for (int k = 0; k < tableData.getData().size(); k++) {
				if (component instanceof Image) {
					tableData.getData().get(k).remove(dataBinding.getDataField());
				}
			}
			if (dataBinding instanceof ILookup) {
				LookupInfo lookupInfo = ((ILookup) (dataBinding)).getLookupInfo();
				if (lookupInfo != null) {
					if (lookupInfo.getDataSourceConfig() != null) {
						List<Map<String, Object>> dataList = tableData.getData();
						Set<Object> keyValueSet = new HashSet<Object>();
						for (int k = 0; k < dataList.size(); k++) {
							Object value = (Object) dataList.get(k).get(dataBinding.getDataField());
							if (value != null) {
								keyValueSet.add(value);
							}
						}
						if (keyValueSet.size() == 0) {
							continue;
						}
						List<SelectItem> selectItemList = lookupUtil.getSelectItemList(yunContext, lookupInfo,
								keyValueSet);
						if (selectItemList != null) {
							selectItemMap.put(component.getId(), selectItemList);
						}
					} else {
						List<SelectItem> selectItemList = lookupUtil.getSelectItemList(yunContext, lookupInfo);
						if (selectItemList != null) {
							selectItemMap.put(component.getId(), selectItemList);
						}
					}
				}
			}
		}
	}
	
	public void getFormComponentData(YunContext yunContext,Page page,List<IDataBinding> formDtaBindingList,List<Table> tableList,Query query) {
		DataSourceConfig mainDataSourceConfig = dataSourceUtil.getDataSourceConfigById(yunContext.getPage(),
				((IDataBindSource)formDtaBindingList.get(0)).getDataSource());
		dataSourceUtil.fillQuery(yunContext, query, mainDataSourceConfig);
		
		com.codeoss.framework.data.metadata.Table mainTable=tableStore.get(mainDataSourceConfig.getTableName());
		SelectRequest selectRequest=new SelectRequest();
		selectRequest.setMainTable(mainTable);
		selectRequest.setMainQuery(query);
		
		for (int i = 0; i < tableList.size(); i++) {
			Table table=tableList.get(i);
			DataSourceConfig dataSourceConfig = dataSourceUtil.getDataSourceConfigById(yunContext.getPage(),table.getDataSource());
			com.codeoss.framework.data.metadata.Table ttable=tableStore.get(dataSourceConfig.getTableName());
			selectRequest.addSubTable(ttable);
			Query subQuery=new Query();
			dataSourceUtil.fillQuery(yunContext, subQuery, dataSourceConfig);
			List<String> subQueryColumnList=page.getAttribute("key_table_field_list" + table.getId()+"_querycolumn");
			subQuery.setSelectColumnList(subQueryColumnList);
			selectRequest.addSubQuery(ttable.getTableName(), subQuery);
		}
		
		SelectResponse selectResponse=pageBeanCRUDUtil.select(yunContext, selectRequest);
		TableData tableData=selectResponse.getTableDataMap().get(mainTable.getTableName());
		Object idValue=null;
		if (tableData.getData().size() > 0) {
			Map<String, Object> dataMap = (Map<String, Object>) tableData.getData().get(0);
			idValue = dataMap.get(mainTable.getPrimaryKeyColumn().getColumnName());
			yunContext.setCurrentId(idValue);
			for (int i = 0; i < formDtaBindingList.size(); i++) {
				IDataBinding dataBinding = formDtaBindingList.get(i);
				if(!(dataBinding instanceof Image)) {
					Object value = dataMap.get(dataBinding.getDataField());
					variableService.setVariableValue(yunContext, ((IVarName)dataBinding).getVarName(), value);
				}
			}
		}
		pageBeanUtil.generateFormInfo(formDtaBindingList);
		
		for (int i = 0; i < tableList.size(); i++) {
			com.codeoss.framework.view.component.Table table = tableList.get(i);
			List<IDataBinding> dataBindingList = page.getAttribute("key_table_field_list" + table.getId());
			DataSourceConfig dataSourceConfig = dataSourceUtil.getDataSourceConfigById(yunContext.getPage(),table.getDataSource());
			com.codeoss.framework.data.metadata.Table subTable = tableStore.get(dataSourceConfig.getTableName());
			TableData subTableData=selectResponse.getTableDataMap().get(subTable.getTableName());
			if(subTableData==null) {
				subTableData=new TableData();
			}
			pageBeanUtil.generateEditableTableInfo(table, dataBindingList, subTableData);
		}
	}
	
	public void getMobileFormComponentData(YunContext yunContext,Page page,List<IDataBinding> formDtaBindingList,List<MListView> listViewList,Query query) {
		DataSourceConfig mainDataSourceConfig = dataSourceUtil.getDataSourceConfigById(yunContext.getPage(),
				((IDataBindSource)formDtaBindingList.get(0)).getDataSource());
		dataSourceUtil.fillQuery(yunContext, query, mainDataSourceConfig);
		
		com.codeoss.framework.data.metadata.Table mainTable=tableStore.get(mainDataSourceConfig.getTableName());
		SelectRequest selectRequest=new SelectRequest();
		selectRequest.setMainTable(mainTable);
		selectRequest.setMainQuery(query);
		
		for (int i = 0; i < listViewList.size(); i++) {
			MListView listView=listViewList.get(i);
			DataSourceConfig dataSourceConfig = dataSourceUtil.getDataSourceConfigById(yunContext.getPage(),listView.getDataSource());
			com.codeoss.framework.data.metadata.Table ttable=tableStore.get(dataSourceConfig.getTableName());
			selectRequest.addSubTable(ttable);
			Query subQuery=new Query();
			dataSourceUtil.fillQuery(yunContext, subQuery, dataSourceConfig);
			List<String> subQueryColumnList=page.getAttribute("key_listview_field_list" + listView.getId()+"_querycolumn");
			subQuery.setSelectColumnList(subQueryColumnList);
			selectRequest.addSubQuery(ttable.getTableName(), subQuery);
		}
		
		SelectResponse selectResponse=pageBeanCRUDUtil.select(yunContext, selectRequest);
		TableData tableData=selectResponse.getTableDataMap().get(mainTable.getTableName());
		Object idValue=null;
		if (tableData.getData().size() > 0) {
			Map<String, Object> dataMap = (Map<String, Object>) tableData.getData().get(0);
			idValue = dataMap.get(mainTable.getPrimaryKeyColumn().getColumnName());
			yunContext.setCurrentId(idValue);
			for (int i = 0; i < formDtaBindingList.size(); i++) {
				IDataBinding dataBinding = formDtaBindingList.get(i);
				if(!(dataBinding instanceof Image)) {
					Object value = dataMap.get(dataBinding.getDataField());
					variableService.setVariableValue(yunContext, ((IVarName)dataBinding).getVarName(), value);
				}
			}
		}
		pageBeanUtil.generateFormInfo(formDtaBindingList);
		
		for (int i = 0; i < listViewList.size(); i++) {
			MListView listView = listViewList.get(i);
			List<IDataBinding> dataBindingList = page.getAttribute("key_listview_field_list" + listView.getId());
			DataSourceConfig dataSourceConfig = dataSourceUtil.getDataSourceConfigById(yunContext.getPage(),listView.getDataSource());
			com.codeoss.framework.data.metadata.Table subTable = tableStore.get(dataSourceConfig.getTableName());
			TableData subTableData=selectResponse.getTableDataMap().get(subTable.getTableName());
			if(subTableData==null) {
				subTableData=new TableData();
			}
			pageBeanUtil.generateMListViewInfo(listView, dataBindingList, subTableData);
		}
	}
	
	public Object getDefaultValue(YunContext yunContext,Page page,IFormFieldExpression formFieldExpression) {
		IDataBinding dataBinding=(IDataBinding)formFieldExpression;
		String ddefaultValue=page.getPageContext("default_"+dataBinding.getDataField());
		if(!StringUtils.isEmpty(ddefaultValue)) {
			Expression expression=new Expression();
			expression.setScriptType(Expression.EXPRESSION_TYPE_JAVASCRIPT);
			expression.setScript(ddefaultValue);
			Object defaultValue=scriptServiceStore.getScriptService(expression).eval(expression.getScript(), yunContext.getVarValueMap());
			return defaultValue;
		}
		
		Expression defaultValueExpression=((IFormFieldExpression)dataBinding).getDefaultValueExpression();
		if(defaultValueExpression!=null) {
			Object defaultValue=scriptServiceStore.getScriptService(defaultValueExpression).eval(defaultValueExpression.getScript(), yunContext.getVarValueMap());
			return defaultValue;
		}
		return null;
	}
}
